Skip to content

Conversation

@atheo89
Copy link
Member

@atheo89 atheo89 commented Nov 4, 2025

Related to: https://issues.redhat.com/browse/RHAIENG-1489
and partially to: https://issues.redhat.com/browse/RHAIENG-1649

Description

This PR introduces pylock_generator.sh, a Bash automation tool that generates
uv lock files (pylock.toml) for all supported notebook image flavors and runtimes.

Key features:

  • Supports targeted mode (specific directory) and automatic mode (repo-wide)
  • Detects available Dockerfiles (CPU, CUDA, ROCm) and locks accordingly
  • Supports two modes of indexes. aipcc-index → Uses internal Red Hat AIPCC wheel indexes and generates per-flavor locks (uv.lock/pylock..toml). And public-index → Uses public PyPI index and updates pylock.toml in-place in the project directory. This Index is currently by default as our odh images are not yet ready to use aipcc wheels. Once ready we can simply tune the to INDEX_MODE=aipcc-index.
  • Includes detailed progress and error reporting
  • Reduces duplication and complexity in the Makefile

How can be used

Using the makefile recipe or run the script directly.

Modes:

  1. Run for in automatic mode (repo-wide)
    via makefile: gmake refresh-lock-files Or the script like: bash scripts/pylocks_generator.sh

  2. Specify the index you desire (for now default is the public pypi)
    gmake refresh-lock-files INDEX_MODE=aipcc-index or bash scripts/pylocks_generator.sh aipcc-index

  3. Lock using public index and specific directory:

gmake refresh-lock-files INDEX_MODE=aipcc-index DIR=jupyter/minimal/ubi9-python-3.12 or bash scripts/pylocks_generator.sh public-index jupyter/minimal/ubi9-python-3.12

--
NOTE: If there is a missing package on pyproject.toml it will produces the following(for example):

  × No solution found when resolving dependencies:
  ╰─▶ Because kubeflow-training was not found in the package registry and datascience-notebook depends on kubeflow-training==1.9.3, we can conclude that your requirements are unsatisfiable.

so in this case you can comment out problematic package in the above case the kubeflow-training, and run it again, and probably it will print another missing package, and so on. So these missing packages should be reported to AIPCC team.

Merge criteria:

  • The commits are squashed in a cohesive manner and have meaningful messages.
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work

Summary by CodeRabbit

  • Chores
    • Added automation to generate per-target Python dependency lock files for multiple hardware flavors (CPU, CUDA, ROCm) with selectable index modes (public-index vs aipcc-index).
    • Validates and skips non-conforming targets, records per-target successes/failures, cleans up on failure, prints remediation guidance, and returns a non-zero exit on any failure.
    • Exposed a new INDEX_MODE variable and streamlined build target to invoke the lock-generation workflow; supports optional per-directory invocation.

@openshift-ci openshift-ci bot requested review from dibryant and jiridanek November 4, 2025 19:46
@github-actions github-actions bot added the review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel label Nov 4, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 4, 2025

Walkthrough

Adds a Bash script that discovers Python projects, validates ubi9-python-X.Y directory names, detects Dockerfile flavors, and generates per-flavor or in-place Python lock files (supports aipcc-index and public-index). Updates the Makefile to add INDEX_MODE and a refresh-lock-files target that invokes the script.

Changes

Cohort / File(s) Change Summary
Lock file generator script
scripts/pylocks_generator.sh
New Bash utility that scans target dirs (jupyter, runtimes, rstudio, codeserver or provided DIR) for pyproject.toml, validates ubi9-python-X.Y directory names, detects Dockerfile flavors (Dockerfile.cpu, Dockerfile.cuda, Dockerfile.rocm), requires uv >= 0.4.0, and runs uv pip compile per flavor. Produces uv.lock / pylock.<flavor>.toml under aipcc-index or updates pylock.toml for public-index. Tracks successes/failures, cleans partial outputs on failure, prints per-dir status and exits non-zero if any failure.
Makefile changes
Makefile
Adds public variable INDEX_MODE (default public-index) and docs; removes refresh-pipfilelock-files; adds refresh-lock-files (PHONY) supporting optional DIR and invoking scripts/pylocks_generator.sh with INDEX_MODE. Replaces prior Pipfile.lock regeneration block with delegation to the new script and updates related build prerequisites.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Check callers/CI for references to the removed refresh-pipfilelock-files target.
  • Verify pylocks_generator.sh correctly parses ubi9-python-X.Y names and handles missing/old uv.
  • Confirm Dockerfile flavor detection matches repository naming and expected flavor set.
  • Validate cleanup of partial lock files and accuracy of SUCCESS/FAILED reporting.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding an automated dependency lock generation script, which matches the primary purpose of the PR.
Description check ✅ Passed The PR description covers the required sections: detailed description of changes, usage examples, and merge criteria checklist with all items checked.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci bot added size/l and removed size/l labels Nov 4, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
scripts/pylocks_generator.sh (3)

7-9: Quote the $index variable for consistency and defensive coding.

While the unquoted expansion on line 97 works correctly (the URL has no spaces and expands as a single argument), it's inconsistent with other quoted variables in the command and less defensive. Quote it for consistency.

   $HAS_CPU && run_lock "cpu" "$CPU_INDEX"
   $HAS_CUDA && run_lock "cuda" "$CUDA_INDEX"
   $HAS_ROCM && run_lock "rocm" "$ROCM_INDEX"

Then in the run_lock function:

     uv pip compile pyproject.toml \
       --output-file "$output" \
       --format pylock.toml \
       --generate-hashes \
       --emit-index-url \
       --python-version="$PYTHON_VERSION" \
       --python-platform linux \
       --no-annotate \
-      $index
+      "$index"

Also applies to: 97-97


101-107: Consider capturing and logging uv pip compile stderr for better diagnostics.

When uv pip compile fails on line 98, the error output is not captured or logged. This makes it difficult for users to diagnose failures when they occur (e.g., missing dependencies, invalid Python version, malformed pyproject.toml).

Consider capturing stderr to help users debug:

    if [ $status -ne 0 ]; then
      warn "${flavor^^} lock failed in $TARGET_DIR"
      warn "Stderr output: $(uv pip compile ... 2>&1 || true)"
      rm -f "$output"
      DIR_SUCCESS=false
    else

Alternatively, document that users can re-run the command manually with full output for debugging.


24-25: Add validation for targeted directory input.

When a user provides a targeted directory via command-line argument (line 25), the script doesn't validate that the directory exists or contains pyproject.toml. This leads to opaque failures later (e.g., during cd or when uv pip compile can't find pyproject.toml).

Add validation after line 25:

if [ $# -gt 0 ]; then
  TARGET_DIRS=("$1")
  if [ ! -d "$1" ] || [ ! -f "$1/pyproject.toml" ]; then
    error "Target directory '$1' does not exist or does not contain pyproject.toml"
    exit 1
  fi

This provides immediate, actionable feedback to users.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 731c89f and 0061bce.

📒 Files selected for processing (1)
  • scripts/pylocks_generator.sh (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: code-static-analysis
🔇 Additional comments (1)
scripts/pylocks_generator.sh (1)

1-2: Solid error handling setup.

The shebang and set -euo pipefail establish safe defaults that will catch and exit on errors, undefined variables, and pipeline failures.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/pylocks_generator.sh (1)

90-116: Quote the $index variable to prevent word-splitting.

Line 105 uses an unquoted $index variable in the uv pip compile command. Although the current index URLs don't contain spaces, this is fragile and violates defensive shell scripting practices. Unquoted variables can cause word-splitting if they ever contain spaces or special characters.

Apply this diff to quote the variable:

  uv pip compile pyproject.toml \
    --output-file "$output" \
    --format pylock.toml \
    --generate-hashes \
    --emit-index-url \
    --python-version="$PYTHON_VERSION" \
    --python-platform linux \
    --no-annotate \
-   $index
+   "$index"
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0061bce and a649bff.

📒 Files selected for processing (1)
  • scripts/pylocks_generator.sh (1 hunks)
🔇 Additional comments (3)
scripts/pylocks_generator.sh (3)

24-27: ✅ Pre-flight check for uv is now in place.

The script now properly detects if the uv command is available and provides a clear error message with installation guidance. This addresses the past critical concern.


118-128: Flavor processing and result aggregation looks good.

The conditional execution of run_lock for each detected flavor is efficient, and the DIR_SUCCESS flag correctly aggregates per-flavor results (marking the entire directory as failed if any flavor fails). Directory tracking and cleanup are proper.


139-153: Summary reporting is clear and user-friendly.

The final summary cleanly separates successful and failed directories, provides actionable remediation guidance for failures (comment out missing packages, report to aipcc team), and is formatted for easy scanning. This aligns well with the PR objectives.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 11, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jiridanek

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@jiridanek jiridanek changed the title feat: add automated dependency lock generation script RHAIENG-1489: feat: add automated dependency lock generation script Nov 11, 2025
@openshift-ci openshift-ci bot added size/l and removed size/l labels Nov 11, 2025
…m to use whatever we need according our needs
@openshift-ci openshift-ci bot removed the lgtm label Nov 12, 2025
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 12, 2025

New changes are detected. LGTM label has been removed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bad8743 and 797e6b7.

📒 Files selected for processing (2)
  • Makefile (3 hunks)
  • scripts/pylocks_generator.sh (1 hunks)
🔇 Additional comments (2)
Makefile (2)

119-119: Addition of refresh-lock-files to skip-init-for list is correct.

This prevents the lock-refresh target from requiring the bin/buildinputs prerequisite, which is appropriate since refreshing lock files does not need Dockerfile dependency analysis.


412-425: New refresh-lock-files target is well-structured.

The target properly documents usage, accepts optional DIR and INDEX_MODE parameters, and cleanly delegates to the script. When DIR is empty, the script auto-discovers projects from MAIN_DIRS, which is the intended behavior.

Note: Ensure the critical ROOT_DIR fix (from the earlier comment) is applied before this target is used, to guarantee paths are resolved correctly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
scripts/pylocks_generator.sh (1)

177-185: Minor style note: unquoted $index variable.

While the index URLs are safely formed without spaces, quoting "$index" would be a defensive best practice:

- $index
+ "$index"

Not critical here, but improves robustness against future changes.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 797e6b7 and 8a3910b.

📒 Files selected for processing (2)
  • Makefile (3 hunks)
  • scripts/pylocks_generator.sh (1 hunks)
🔇 Additional comments (8)
scripts/pylocks_generator.sh (5)

59-62: Preflight check for uv command is in place.

The script correctly verifies uv availability and exits cleanly with a helpful error message if missing. ✓


128-134: Python version extraction validation is in place.

The regex check ^[0-9]+\.[0-9]+$ correctly validates the major.minor format and skips invalid directories with a clear warning. ✓


159-200: run_lock function correctly handles errors and cleanup.

The pattern of set +e → capture $?set -e is the right way to catch exit codes in strict mode. Cleanup on failure (line 191) prevents partial artifacts. ✓


119-219: Main loop logic is sound.

Directory discovery, Python version validation, Dockerfile detection, and per-flavor lock generation are all correctly sequenced. The cd "$TARGET_DIR" || continue pattern safely handles permission or access issues. ✓


236-244: Exit code handling correctly reports failures to CI/Make.

The script exits with status 1 if any lock generation fails (line 243), allowing Make targets and CI pipelines to properly detect and fail on errors. ✓

Makefile (3)

28-29: INDEX_MODE variable correctly defined without redefining ROOT_DIR.

The prior issue of ROOT_DIR redefinition is fixed. INDEX_MODE is appropriately defined with clear comment. ✓


118-118: refresh-lock-files correctly added to skip-init-for list.

This prevents buildinputs from being unnecessarily triggered when running lock generation, which is the correct behavior. ✓


411-424: New refresh-lock-files target is well-structured.

The target:

  • Accepts optional DIR parameter for repo-wide (default) or directory-specific lock generation
  • Includes comprehensive usage documentation
  • Correctly invokes scripts/pylocks_generator.sh with both INDEX_MODE and DIR
  • Uses @cd $(ROOT_DIR) to ensure correct working directory

Integration with the Bash script is clean and follows the documented API. ✓

@atheo89 atheo89 added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Nov 12, 2025
@atheo89 atheo89 changed the title RHAIENG-1489: feat: add automated dependency lock generation script RHAIENG-1649: feat: add automated dependency lock generation script Nov 12, 2025
@openshift-ci openshift-ci bot added size/l and removed size/l labels Nov 12, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
Makefile (1)

424-424: Quote variables in shell invocation for robustness.

Variables passed to the shell script should be quoted to handle edge cases (e.g., if DIR contains spaces or special characters). While INDEX_MODE is Makefile-controlled and safe, DIR is user-provided.

-	@cd $(ROOT_DIR) && bash scripts/pylocks_generator.sh $(INDEX_MODE) $(DIR)
+	@cd $(ROOT_DIR) && bash scripts/pylocks_generator.sh "$(INDEX_MODE)" "$(DIR)"

This follows the pattern used elsewhere in the Makefile (e.g., line 86: --dockerfile '$(2)') and prevents potential word-splitting or globbing issues.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a3910b and 7d3732a.

📒 Files selected for processing (2)
  • Makefile (3 hunks)
  • scripts/pylocks_generator.sh (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (31)
  • GitHub Check: build (runtime-cuda-pytorch-llmcompressor-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (rocm-jupyter-pytorch-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-jupyter-tensorflow-ubi9-python-3.12, 3.12, linux/arm64, false) / build
  • GitHub Check: build (runtime-cuda-tensorflow-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (runtime-cuda-tensorflow-ubi9-python-3.12, 3.12, linux/arm64, false) / build
  • GitHub Check: build (runtime-datascience-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-jupyter-tensorflow-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (jupyter-minimal-ubi9-python-3.12, 3.12, linux/ppc64le, false) / build
  • GitHub Check: build (cuda-rstudio-c9s-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (jupyter-trustyai-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (codeserver-ubi9-python-3.12, 3.12, linux/arm64, false) / build
  • GitHub Check: build (runtime-cuda-pytorch-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (rocm-jupyter-tensorflow-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (jupyter-datascience-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (jupyter-datascience-ubi9-python-3.12, 3.12, linux/ppc64le, false) / build
  • GitHub Check: build (jupyter-minimal-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (runtime-datascience-ubi9-python-3.12, 3.12, linux/s390x, false) / build
  • GitHub Check: build (runtime-minimal-ubi9-python-3.12, 3.12, linux/s390x, false) / build
  • GitHub Check: build (codeserver-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (rocm-runtime-tensorflow-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-jupyter-pytorch-llmcompressor-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (rocm-runtime-pytorch-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-jupyter-minimal-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-jupyter-pytorch-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (jupyter-minimal-ubi9-python-3.12, 3.12, linux/s390x, false) / build
  • GitHub Check: build (rocm-jupyter-minimal-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (runtime-minimal-ubi9-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-jupyter-minimal-ubi9-python-3.12, 3.12, linux/arm64, false) / build
  • GitHub Check: build (rstudio-c9s-python-3.12, 3.12, linux/amd64, false) / build
  • GitHub Check: build (cuda-rstudio-rhel9-python-3.12, 3.12, linux/amd64, true) / build
  • GitHub Check: build (rstudio-rhel9-python-3.12, 3.12, linux/amd64, true) / build
🔇 Additional comments (1)
scripts/pylocks_generator.sh (1)

1-248: Excellent work addressing all prior concerns—script is production-ready.

All three critical issues flagged in previous reviews have been properly resolved:

  1. ✅ Pre-flight check for uv command availability (lines 63–66)
  2. ✅ Python version extraction validation with regex (lines 133–138)
  3. ✅ Exit code signaling on lock generation failures (line 247)

The script demonstrates solid bash practices: safe file-finding patterns (-print0 with read -d ''), proper error handling (set +e/set -e), helpful colored output, clear error messages, and comprehensive documentation. The separation of public-index vs. aipcc-index logic and per-flavor lock generation is clean and maintainable.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 17, 2025

@atheo89: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/images 7d3732a link true /test images

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@atheo89 atheo89 merged commit 01c24b8 into opendatahub-io:main Nov 18, 2025
30 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel size/l tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants